# Wizard Battle
# Two wizards dueling
#   Given different functions with which to fire
##      Rather than having the type of damage based on the path/function,
##      I was thinking that we would have different spells or energy types
##      that would be used in conjunction with a path to achieve the
##      desired effect.
##  So, we would have spells like
##  1) Destructoball - obliterates terrain and obstacles in its path but
##      does weak damage to Wizzards
##  2) Concussion Blast - knocks down/back obstacles but does not travel
##      through or destroy terrain; medium to high damage to Wizzards
##  3) Noodly Appendage Of Death - does not travel through or destroy
##      terrain or obstacles; deals very high damage to Wizzards
##  4) ???
##  5) profit!

##  These, then, would be the paths the players can select for their
##  spells to travel along
#   1) Linear
#   2) n-order polynomial
#   3) Sinusoidal function
#   4) combo polynomial sinusoidal

##  This would afford the players an unprecedented (as far as I know)
##  amount of control over the effects of their casts, and make for
##  what I think will be some very interesting gameplay options.

##  I predict these will be highly iterated aspects of the game.

##  The selection space of user actions seems fairly limited right now --
##  I think maps will play a large role in how interesting gameplay is.

##  I have no idea what I'm doing with these classes. Here goes.

import pygame
from math import *

# EVENT DECLARATIONS GO HERE

SUPER_STATE = pygame.USEREVENT    # 24
WIZZARD = SUPER_STATE + 1         # 25  
"""WIZZARD status attribute: (string)
    damaged -- Wizzard has been damaged, usually by a spell
    dead -- Wizzard's health has been reduced below zero
"""
FOCUS_CHANGE = WIZZARD + 1        # 26
"""FOCUS_CHANGE focus attribute: (string)
    nextWizzard -- ends turn
    curWizzard -- returns focus to current wizzard
    redWizzard -- sets focus to red Wizzard
    blueWizzard -- sets focus to blue Wizzard
    menu -- creates menu and sets focus to it
"""
SPELL_CAST = FOCUS_CHANGE + 1     # 27
"""SPELL_CAST spell attribute: (spellSprite)
    contains a spellSprite to be added to the PyManMain.sprites
"""

def add(x, y):
    return x+y

class spell:
    spelltype = "none"

## power levels are based on Wizzards having 100 health

class dball(spell):
    """Destructo-ball:
        Destroys everything in its path
        Very weak damage"""
    spelltype = "dball"
    terrain = "destroy"
    obstacle = "destroy"
    radius = 5
    power = 10

class cblast(spell):
    """Concussion Blast:
        Knocks back obstacles
        Fizzles on terrain
        Moderate damage"""
    spelltype = "cblast"
    terrain = "fizzle"
    obstacle = "knock"
    radius = 3
    power = 40

class nooad(spell):
    """NOOdly Appendage of Death
        Fizzles on terrain and obstacles
        Very high damage"""
    spelltype = "nooad"
    terrain = "fizzle"
    obstacle = "fizzle"
    radius = 1
    power = 80

class profit(spell):
    spelltype = "profit"

class path: ## since the following classes now describe paths instead of spells
    pathtype= "none"

class lin(path):
    def __init__(self):
        self.coeff = a
        self.const = b
    pathtype = "linear"
    def func(x):
        return self.coeff * x + self.const

class npoly(path):
    def __init__(self, n, coeffs):
        self.order = n
        self.coeff = coeffs
    pathtype = "npoly"
    def func():
        runpoly(self.coeff, self.order)

class sinu(path):
    def __init__(self, coeffs, power):
        self.power = power
        self.coeff = coeffs
    pathtype = "sinu"
    def gfunc():
        return 1
    def func():
        runsinu(self.coeff, self.power)

class gfuncsinu(sinu):
    def __init__(self, coeffs, power, n, pcoeffs):
        self.coeff = coeffs
        self.power = power
        self.order = n
        self.polycoeff = pcoeffs
    pathtype = "sinugfunc"
    def gfunc():
        runpoly(pcoeffs, power)
    def func():
        runsinu(coeff, power)
    
#class Wizzard:
# Now in wizzardSprite.py

def runpoly(x, pcoeffs, power):
    # This won't work!
    pfunc = []
    for i in range(len(pcoeffs)):
        pfunc.append(x**(i) * pcoeffs[i])
    xsol = evalpfunc(x, pfunc)
    return xsol
    
def evalpfunc(x, pfunc):
    xsol = 0
    for func in pfunc:
        xsol += func
    print "xsol " + str(xsol)
    return xsol
        
def runsinu(x, coeff, power):
    func = coeff * sin(x*2*pi/360)**power
    return func
    
def runmix(x, sincoeff, sinpow, polycoeffs, polypower):
    func1 = runsinu(x, sincoeff, sinpow)
    func2 = runpoly(x, polycoeffs, polypower)
    func = func1*func2
    return func

def createpath(val1, val2):
    """this should interpolate a discrete 'continuous curve' between two points"""
    val1x = val1[0]
    val1y = val1[1]
    val2x = val2[0]
    val2y = val2[1]
    xdist = 3
    ydist = ceil(val2y - val1y)
    path = split(xdist, ydist)
    return(path)

def split(x, y):
    """ This basically finds pieces of the path from one point to another"""
    path=[]
    sgn = [0, 0]
    #This if function figures out whether we have a larger x or y distance, then
    #calculates how many x's per y should be used
    if (x == 0):
        splt = [0, 1]
    elif (y == 0):
        splt = [0, 0]
    elif (abs(x) > abs(y)):
        splt = [floor(x/y), 0]
    else:
        splt = [floor(y/x), 1]
    #These two ifs check the sign of the x and y directions so I don't end up going backwards 
    if y - 150 > 0:
        sgn[1] = 0
    else:
        sgn[1] = 1
    if x > 0:
        sgn[0] = 0
    else:
        sgn[0] = 1
    #This for loop determines the direction to go per pixel
    #(splt[1] + 1) % 2 gives the lesser direction
    # i % splt[0] == 0 says if we've run into a time to use the lesser direction
    for i in range(x+y):
        if (splt[0] != 0 and i % splt[0] == 0):
            m = int((splt[0] + 1)%2)
            path.append([m, sgn[m]])
        else:
            path.append([splt[1], sgn[splt[1]]])
    return(path)

def followpth(sx, sy, pth, i):
# this checks whether we're going in the x direction or the y direction.
# the (-1)^(pth[i, 1]) checks the sgn of the movement, if path[i, 1] = 1, then
# it's negative movement, thus (-1)^(pth[i, 1]) = -1, otherwise it's 1.
    if pth[i][0] == 0:
        sx += (-1)^(pth[i][1])
    else:
        sy += (-1)^(pth[i][1])
    return([sx, sy])
    
    
